import modes as mc
import tkinter as tk
from tkinter import ttk
import threading
import base_mode as bm

IS_BOARD = True

try:
    from pinpong.board import Board, Pin, NeoPixel
    from unihiker import GUI
    gui = GUI()
except ModuleNotFoundError:
    print("警告：非行空板环境")
    IS_BOARD = False
import time


class XingkongBoardBase:
    def __init__(self):
        pass

    def on_btn_click(self, callback):
        """
        按下机外的那个按钮。
        该按钮按键流程（必须辩论模式）：
            1. 进入立论模式（若是正方，则直接说话；若是反方，则直接开始录音）
            2. 当本方为正方时，开始录（反方）音；为反方时，停止录（正方的）音
            3. 当本方为正方时，停止录（反方）音；为反方时，开始说话
            4. 当本方为正方时，进入进入自由辩论模式；为反方时，也是进入自由辩论模式（请确保灯光为绿）
            5. 关闭自由辩论模式
            6. 进入总结陈词模式。为正方时将直接开始录音；为反方时将直接输出语音，完成后辩论模式结束
            7. 正方停止录音
            8. 正方输出语音。完成后辩论模式结束
        :param callback: 当按下时的回调函数
        :return:
        """
        pass

    def on_btn_dialog_click(self, callback):
        """
        按下“对话模式”按钮
        :param callback: 当按下时的回调函数
        :return:
        """
        pass

    def on_btn_debate_click(self, callback):
        """
        按下“辩论模式”按钮
        :param callback: 当按下时的回调函数
        :return:
        """
        pass

    def on_btn_stop_click(self, callback):
        """
        按下“停止”按钮
        :param callback: 当按下时的回调函数
        :return:
        """
        pass

    def set_light_color(self, color):
        """
        设置灯光颜色。
        在对话模式和自由辩论模式不设置灯光颜色。
        red: 正在处理一些事件，此时不能点击机外按钮
        green: 准备就绪，可以点击机外按钮
        blue: 正在录音
        orange: 成功进入辩论模式和自由辩论
        :param color: "red"|"green"|"blue"|"orange"
        :return:
        """
        pass


SYSTEM = \
    """
    你是人大附中经开学校金鹏科技团开发的辩论智能体机器人，名叫人开一号。
    这个机器人运用了流式语音识别、大语言模型、流式语音合成等技术。
    当你被要求介绍自己时，请简要介绍你的功能和技术实现。
    请注意，你的回答将被直接通过语音合成输出，因此你不能输出不适合TTS的内容。
    """


class Unihiker_Board(XingkongBoardBase):
    def __init__(self):
        super().__init__()
        Board().begin()
        # self.gui=GUI()
        self.btn21 = Pin(Pin.P21, Pin.IN)
        self.pin23 = Pin(Pin.D23)
        self.np1 = NeoPixel(self.pin23, 22)
        self.np1.brightness(150)
        gui.add_button(x=0, y=290, w=80, h=30, text="对话", origin='nw', onclick=self._trigger_dialog_click)
        gui.add_button(x=80, y=290, w=80, h=30, text="辩论", origin='nw', onclick=self._trigger_debate_click)
        gui.add_button(x=160, y=290, w=80, h=30, text="停止", origin='nw', onclick=self._trigger_stop_click)

        self.btn_count = 0

        self.btn_callback = None
        self.dialog_callback = None
        self.debate_callback = None
        self.stop_callback = None

    def on_btn_click(self, callback):
        self.btn_callback = callback

    def on_btn_dialog_click(self, callback):
        self.dialog_callback = callback

    def on_btn_debate_click(self, callback):
        self.debate_callback = callback

    def on_btn_stop_click(self, callback):
        self.stop_callback = callback

    def set_light_color(self, color):
        if color == "red":
            self.np1.range_color(0, 21, 0xFF0000)
        if color == "green":
            self.np1.range_color(0, 21, 0x00FF00)
        if color == "blue":
            self.np1.range_color(0, 21, 0x0000FF)
        if color == "orange":
            self.np1.range_color(0, 21, 0xFFFF00)

    def _trigger_btn_click(self):
        if self.btn_callback:
            threading.Thread(target=self.btn_callback, daemon=True).start()

    def _trigger_dialog_click(self):
        if self.dialog_callback:
            threading.Thread(target=self.dialog_callback, daemon=True).start()

    def _trigger_debate_click(self):
        if self.debate_callback:
            threading.Thread(target=self.debate_callback, daemon=True).start()

    def _trigger_stop_click(self):
        if self.stop_callback:
            threading.Thread(target=self.stop_callback, daemon=True).start()

    def btn_click_check(self):
        while True:
            if self.btn21.read_digital() == 0:
                while self.btn21.read_digital() == 0:
                    pass
                self._trigger_btn_click()

    def run(self):
        threading.Thread(target=self.btn_click_check, daemon=True).start()
        while True:
            time.sleep(1)


class Robot:
    def __init__(self, board: XingkongBoardBase):
        self.modes = dict()
        self.btn_count = 0
        self.board = board
        self.side = ""
        self.topic = ""
        self.opinion = ""
        self.last_prompt = ""
        self.session_id = None

    def register_mode(self, modename: str, mode: bm.Mode):
        self.modes[modename] = mode

    def run_mode(self, modename):
        self.modes[modename].run()

    def stop_mode(self, modename):
        self.modes[modename].stop()
        del self.modes[modename]

    def get_mode(self, modename):
        return self.modes[modename]

    def stop_all(self):
        for mode in self.modes.values():
            mode.stop()
        self.modes.clear()

    def dialog(self):
        self.stop_all()
        self.board.set_light_color("orange")
        dialog_mode = mc.DialogMode(system_prompt=SYSTEM)
        self.register_mode("dialog", dialog_mode)
        self.run_mode("dialog")

    def set_debate_config(self, side, topic, opinion):
        self.side = side
        self.topic = topic
        self.opinion = opinion

    def debate(self):
        self.stop_all()
        self.board.set_light_color("orange")
        self.btn_count = 0
        if self.side == "正方":
            self.board.on_btn_click(self._btn_right_callback)
        else:
            self.board.on_btn_click(self._btn_against_callback)

    def on_cancel(self):
        self.stop_all()
        self.board.set_light_color("green")

    def _btn_right_callback(self):
        self.btn_count += 1
        if self.btn_count == 1:
            self.board.set_light_color("red")
            self.register_mode("make_point", mc.MakePointMode(side=self.side, topic=self.topic, opinion=self.opinion))
            self.run_mode("make_point")
            self.board.set_light_color("green")
        elif self.btn_count == 2:
            md: mc.MakePointMode = self.get_mode("make_point")
            self.board.set_light_color("blue")
            md.start_record()
        elif self.btn_count == 3:
            md: mc.MakePointMode = self.get_mode("make_point")
            self.board.set_light_color("red")
            md.stop_record()
            self.board.set_light_color("green")
            self.last_prompt = md.ready_next()
        elif self.btn_count == 4:
            self.board.set_light_color("red")
            md: mc.MakePointMode = self.get_mode("make_point")
            self.session_id = md.session_id
            self.stop_mode("make_point")
            self.register_mode("free_debate", mc.FreeDebateMode(side=self.side, topic=self.topic, opinion=self.opinion,
                                                                last_prompt=self.last_prompt,
                                                                session_id=self.session_id))
            self.run_mode("free_debate")
            self.board.set_light_color("orange")
        elif self.btn_count == 5:
            self.board.set_light_color("red")
            md: mc.FreeDebateMode = self.get_mode("free_debate")
            self.session_id = md.session_id
            self.stop_mode("free_debate")
            self.board.set_light_color("green")
        elif self.btn_count == 6:
            self.board.set_light_color("red")
            self.register_mode("end_debate", mc.EndDebateMode(side=self.side, topic=self.topic, opinion=self.opinion,
                                                              session_id=self.session_id))
            self.run_mode("end_debate")
            self.board.set_light_color("blue")
        elif self.btn_count == 7:
            md: mc.EndDebateMode = self.get_mode("end_debate")
            md.stop_record()
            self.board.set_light_color("green")
        elif self.btn_count == 8:
            self.board.set_light_color("red")
            md: mc.EndDebateMode = self.get_mode("end_debate")
            md.start_talk()
            self.board.set_light_color("green")
            self.stop_mode("end_debate")


    def _btn_against_callback(self):
        self.btn_count += 1
        if self.btn_count == 1:
            self.board.set_light_color("blue")
            self.register_mode("make_point", mc.MakePointMode(side=self.side, topic=self.topic, opinion=self.opinion))
            self.run_mode("make_point")
        elif self.btn_count == 2:
            md: mc.MakePointMode = self.get_mode("make_point")
            self.board.set_light_color("red")
            md.stop_record()
            self.board.set_light_color("green")
        elif self.btn_count == 3:
            self.board.set_light_color("red")
            md: mc.MakePointMode = self.get_mode("make_point")
            md.ready_next()
            self.board.set_light_color("green")
        elif self.btn_count == 4:
            self.board.set_light_color("red")
            md: mc.MakePointMode = self.get_mode("make_point")
            self.session_id = md.session_id
            self.stop_mode("make_point")
            self.register_mode("free_debate", mc.FreeDebateMode(side=self.side, topic=self.topic, opinion=self.opinion,
                                                                session_id=self.session_id))
            self.run_mode("free_debate")
            self.board.set_light_color("green")
        elif self.btn_count == 5:
            self.board.set_light_color("red")
            md: mc.FreeDebateMode = self.get_mode("free_debate")
            self.session_id = md.session_id
            self.stop_mode("free_debate")
            self.board.set_light_color("green")
        elif self.btn_count == 6:
            self.board.set_light_color("red")
            self.register_mode("end_debate", mc.EndDebateMode(side=self.side, topic=self.topic, opinion=self.opinion,
                                                              session_id=self.session_id))
            self.run_mode("end_debate")
            md: mc.EndDebateMode = self.get_mode("end_debate")
            md.start_talk()

    def run(self):
        self.board.on_btn_dialog_click(self.dialog)
        self.board.on_btn_debate_click(self.debate)
        self.board.on_btn_stop_click(self.on_cancel)


class MockXingkongBoard(XingkongBoardBase):
    def __init__(self):
        super().__init__()
        self.root = tk.Tk()
        self.root.title("模拟控制台")
        self.root.geometry("300x200")

        # 灯光显示
        self.light = tk.Label(self.root, width=10, height=5, bg="gray")
        self.light.pack(pady=10)

        # 按钮布局
        btn_frame = ttk.Frame(self.root)
        btn_frame.pack(pady=10)

        # 机外按钮
        ttk.Button(btn_frame, text="机外按钮", command=self._trigger_btn_click).grid(row=0, column=0, padx=5)

        # 功能按钮
        ttk.Button(btn_frame, text="对话模式", command=self._trigger_dialog_click).grid(row=1, column=0, padx=5)
        ttk.Button(btn_frame, text="辩论模式", command=self._trigger_debate_click).grid(row=1, column=1, padx=5)
        ttk.Button(btn_frame, text="停止", command=self._trigger_stop_click).grid(row=1, column=2, padx=5)

        # 回调存储
        self.btn_callback = None
        self.dialog_callback = None
        self.debate_callback = None
        self.stop_callback = None

    def on_btn_click(self, callback):
        self.btn_callback = callback

    def on_btn_dialog_click(self, callback):
        self.dialog_callback = callback

    def on_btn_debate_click(self, callback):
        self.debate_callback = callback

    def on_btn_stop_click(self, callback):
        self.stop_callback = callback

    def set_light_color(self, color):
        # 仅设置颜色，不添加任何模式判断
        self.light.config(bg=color)

    def _trigger_btn_click(self):
        # 直接触发回调，高耗时操作放线程
        if self.btn_callback:
            threading.Thread(target=self.btn_callback, daemon=True).start()

    def _trigger_dialog_click(self):
        if self.dialog_callback:
            threading.Thread(target=self.dialog_callback, daemon=True).start()

    def _trigger_debate_click(self):
        if self.debate_callback:
            threading.Thread(target=self.debate_callback, daemon=True).start()

    def _trigger_stop_click(self):
        if self.stop_callback:
            threading.Thread(target=self.stop_callback, daemon=True).start()

    def run(self):
        self.root.mainloop()


if __name__ == '__main__':
    board = Unihiker_Board() if IS_BOARD else MockXingkongBoard()
    robot = Robot(board)
    robot.set_debate_config(
        "反方",
        "利用基因技术复活已灭绝物种（反灭绝工程）是生态责任还是资源浪费",
        "利用基因技术复活已灭绝物种（反灭绝工程）是资源浪费"
    ) if IS_BOARD else robot.set_debate_config(
        "反方",
        "量子计算机的实用化是否会首先对现有加密体系构成致命威胁",
        "量子计算机的实用化是否不会首先对现有加密体系构成致命威胁"
    )
    robot.run()
    board.run()
